#include "grammar_scanner.h"
#include "parser.h"
#include "cli.h"
#include "scanner.h"
#include "code_generator.h"
#include "reduced_grammar.h"
#include <iostream>



// Граматика може містити службове слово повторювач - REPEATNTSYMBOL. З нього не виводяться правила і він не записується в структури Rules.
// Основне його призначення - повторення NT-символа, який стоїть перед ним, якщо з цього символа виводиться правило.


int main (int argc, char *argv[])
{
    GrammarScanner grammar_scanner;
    Scanner code_scanner;
    Cli user_interface;
    std::string source_code = user_interface.cli();
    int result = grammar_scanner.startScanner("declaration_variables_grammar");
    std::cout << "\tпочаткова грамматика:\n";
    user_interface.printGrammar(grammar_scanner.getGrammarRules());
    std::cout << '\n' << result << "\n\n";
    std::vector<Rules> without_left_recursion; // грамматика без лівої рекурсії
    eliminationLeftRecursion(grammar_scanner.getGrammarRules(), without_left_recursion);
    std::cout << "\tграмматика без лівої рекурсії:\n";
    user_interface.printGrammar(without_left_recursion);
    result = grammar_scanner.startScanner("declaration_variables_grammar_with_empty_rules");
    std::cout << result << "!!\n";
    std::vector<Rules> with_empty_rules = grammar_scanner.getGrammarRules(); // граматика з ^-правилами
    std::cout << "\tграмматика з ^-правилами:\n";
    user_interface.printGrammar(with_empty_rules);
    Parser parser(/*without_left_recursion*/grammar_scanner.getGrammarRules(), with_empty_rules);
    result = code_scanner.startScanner(source_code);
    std::cout << result << '\n';
    user_interface.printTokens(code_scanner.getTokenTable());
    result = parser.parsing(code_scanner.getTokenTable(), code_scanner.getFunctionsIdentTable());
    std::cout << result << '\n';
    if (!result)
    {
        user_interface.printIdentificatorTable(code_scanner.getFunctionsIdentTable()["main"]);
        std::cout << "\tSyntax tree:\n";
        for (int i = 0; i < parser.getOutputTrees().size(); i++) {
            user_interface.printTree(parser.getOutputTrees()[i]);
        }
        std::cout << "------------------\n";
        CodeGenerator code_generator;
        code_generator.startCodeGenerate(parser.getOutputTrees(), code_scanner.getFunctionsIdentTable());
        std::cout << "\tOperation tree:\n";
        for (int i = 0; i < code_generator.getArrayOutputTrees().size(); i++) {
            user_interface.printOperationTree(code_generator.getArrayOutputTrees()[i]);
        }
        std::cout << "------------------\n";
    }
}
